package cn.ug.mall.service.impl;

import cn.ug.account.bean.DataDictionaryBean;
import cn.ug.activity.bean.CouponMemberBean;
import cn.ug.bean.LoginBean;
import cn.ug.bean.Result;
import cn.ug.bean.ResultItem;
import cn.ug.bean.base.DataTable;
import cn.ug.bean.base.Page;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.ensure.Ensure;
import cn.ug.core.login.LoginHelper;
import cn.ug.enums.*;
import cn.ug.feign.CouponRepertoryService;
import cn.ug.feign.DataDictionaryService;
import cn.ug.feign.MemberAddressService;
import cn.ug.feign.PayGoldBeanRecordService;
import cn.ug.mall.bean.*;
import cn.ug.mall.mapper.*;
import cn.ug.mall.mapper.entity.*;
import cn.ug.mall.service.OrderService;
import cn.ug.mall.service.RateSettingsService;
import cn.ug.mall.web.submit.OrderSearchSubmit;
import cn.ug.mall.web.submit.OrderSubmit;
import cn.ug.member.bean.MemberLogisticsBean;
import cn.ug.msg.bean.status.CommonConstants;
import cn.ug.msg.bean.type.SmsType;
import cn.ug.msg.mq.Sms;
import cn.ug.service.impl.BaseServiceImpl;
import cn.ug.util.SerialNumberWorker;
import cn.ug.util.UF;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import static cn.ug.config.QueueName.QUEUE_MSG_SMS_SEND;
import static cn.ug.util.ConstantUtil.NATIVE_PRI_KEY;

/**
 * @author zhaohg
 * @date 2018/07/10.
 */
@Service
public class OrderServiceImpl extends BaseServiceImpl implements OrderService {

    @Resource
    private OrderMapper           orderMapper;
    @Resource
    private OrderItemMapper       orderItemMapper;
    @Resource
    private GoodsMapper           goodsMapper;
    @Resource
    private GoodsSkuMapper        goodsSkuMapper;
    @Resource
    private NewLogisticsMapper    newLogisticsMapper;
    @Resource
    private DozerBeanMapper       dozerBeanMapper;
    @Resource
    private MemberAddressService  memberAddressService;
    @Resource
    private DataDictionaryService dataDictionaryService;
    @Resource
    private AmqpTemplate          amqpTemplate;
    @Resource
    private RateSettingsMapper    rateSettingsMapper;
    @Resource
    private ProcessTemplateMapper processTemplateMapper;
    @Resource
    private ShoppingTrolleyMapper shoppingTrolleyMapper;
    @Resource
    private KD100Service          kd100Service;
    @Resource
    private RedisGlobalLock       redisGlobalLock;
    @Autowired
    private CouponRepertoryService couponRepertoryService;
    @Autowired
    private RateSettingsService rateSettingsService;
    @Autowired
    private PayGoldBeanRecordService payGoldBeanRecordService;

    @Override
    public SerializeObject validateOrder(String orderNO) {
        if (StringUtils.isBlank(orderNO)) {
            return new SerializeObjectError("00000002");
        }
        OrderEntity order = orderMapper.selectByOrderNO(orderNO);
        if (order == null) {
            return new SerializeObjectError("00000002");
        }
        List<OrderItemEntity> items = orderItemMapper.findListByOrderId(order.getId());
        if (items == null || items.size() == 0) {
            return new SerializeObjectError("00000002");
        }
        Set<Long> goodsIds = new HashSet<Long>();
        for (OrderItemEntity item : items) {
            GoodsSkuEntity skuEntity = goodsSkuMapper.findById(item.getSkuId());
            if (skuEntity == null || item.getNum() > skuEntity.getStock()) {
                if (items.size() > 1) {
                    int stock = skuEntity == null ? 0 : skuEntity.getStock();
                    return new SerializeObject<>(ResultType.STOCK_LACKING, "20300208", item.getSkuId()+":"+stock);
                } else {
                    int stock = skuEntity == null ? 0 : skuEntity.getStock();
                    return new SerializeObject<>(ResultType.STOCK_LACKING, "20300214", item.getSkuId()+":"+stock);
                }
            }
            goodsIds.add(item.getGoodsId());
        }
        List<GoodsPayBean> payBeans = new ArrayList<GoodsPayBean>();
        for (long goodsId : goodsIds) {
            GoodsPayBean bean = new GoodsPayBean();
            bean.setGoodsId(goodsId);
            bean.setTotalGram(BigDecimal.ZERO);
            bean.setTotalNum(0);
            payBeans.add(bean);
        }
        for (OrderItemEntity item : items) {
            for (GoodsPayBean bean : payBeans) {
                if (StringUtils.equals(String.valueOf(item.getGoodsId()), String.valueOf(bean.getGoodsId()))) {
                    bean.setTotalNum(bean.getTotalNum() + item.getNum());
                    bean.setTotalGram(bean.getTotalGram().add(item.getWeight()));
                    break;
                }
            }
        }
        for (GoodsPayBean bean : payBeans) {
            GoodsEntity goodsEntity = goodsMapper.findById(bean.getGoodsId());
            if (goodsEntity == null) {
                return new SerializeObjectError("20300200");
            }
            Calendar calendar = Calendar.getInstance();
            if (goodsEntity.getIsPrompt() == 1 && goodsEntity.getStartPrompt() != null && calendar.getTime().getTime() < goodsEntity.getStartPrompt().getTime()) {
                return new SerializeObjectError("20300202");
            }
            if (goodsEntity.getIsPrompt() == 1 && goodsEntity.getEndPrompt() != null && calendar.getTime().getTime() > goodsEntity.getEndPrompt().getTime()) {
                return new SerializeObjectError("20300202");
            }
            if (goodsEntity.getIsQuota() == 1 && goodsEntity.getQuotaNum() > 0) {
                int num = orderItemMapper.selectNumByMemberId(goodsEntity.getId(), order.getUserId());
                if ((num + bean.getTotalNum()) > goodsEntity.getQuotaNum()) {
                    return new SerializeObjectError("20300203");
                }
            }
            if (goodsEntity.getIsQuota() == 2 && goodsEntity.getQuotaWeight() != null && goodsEntity.getQuotaWeight().doubleValue() > 0) {
                double weight = orderMapper.selectTotalGramByMemberId(goodsEntity.getId(), order.getUserId());
                if ((weight + bean.getTotalGram().doubleValue()) > goodsEntity.getQuotaWeight().doubleValue()) {
                    return new SerializeObjectError("20300207");
                }
            }
        }
        return new SerializeObject<>(ResultType.NORMAL, "00000001");
    }

    @Override
    public List<String> selectGoodsNames(String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            return orderItemMapper.selectGoodsNames(orderNO);
        }
        return null;
    }

    @Override
    @Transactional
    public SerializeObject insert(OrderSubmit submit, long skuId, int quantity) {
        GoodsSkuEntity skuEntity = goodsSkuMapper.findById(skuId);
        if (skuEntity == null || skuEntity.getGoodsId() == 0) {
            return new SerializeObjectError("00000002");
        }
        GoodsEntity goodsEntity = goodsMapper.findById(skuEntity.getGoodsId());
        if (goodsEntity == null) {
            return new SerializeObjectError("00000002");
        }

        SerializeObject<MemberLogisticsBean> addressBean = memberAddressService.getLogisticsAddress(submit.getAddressId());
        if (addressBean != null && addressBean.getData() != null) {
            NewLogisticsEntity logistics = new NewLogisticsEntity();
            logistics.setAddress(addressBean.getData().getAddress());
            logistics.setFullName(addressBean.getData().getFullName());
            logistics.setTelephone(addressBean.getData().getTelephone());
            newLogisticsMapper.insert(logistics);
            OrderEntity entity = dozerBeanMapper.map(submit, OrderEntity.class);
            entity.setLogisticsId(logistics.getId());
            entity.setAmount(BigDecimal.ZERO);
            entity.setMoney(entity.getAmount().add(entity.getExpressFee()).add(entity.getProcessCost()));
            entity.setTotalGram(skuEntity.getGram().multiply(new BigDecimal(quantity)));
            if (entity.getStatus() == 3) {
                entity.setPayTime(Calendar.getInstance().getTime());
            }
            if (orderMapper.insert(entity) > 0) {
                OrderItemEntity itemEntity = new OrderItemEntity();
                itemEntity.setGoodsCode(goodsEntity.getGoodsCode());
                itemEntity.setNum(quantity);
                itemEntity.setOrderId(entity.getId());
                itemEntity.setPrice(skuEntity.getPrice().multiply(new BigDecimal(quantity)));
                itemEntity.setGoodsId(goodsEntity.getId());
                itemEntity.setSkuId(skuId);
                itemEntity.setWeight(skuEntity.getGram().multiply(new BigDecimal(quantity)));
                int raws = orderItemMapper.insert(itemEntity);
                Ensure.that(raws < 1).isTrue("00000005");
                if (entity.getStatus() == 3) {
                    goodsEntity.setSales(goodsEntity.getSales() + quantity);
                    goodsEntity.setStock(goodsEntity.getStock() - quantity);
                    if (goodsEntity.getStock() <= 0) {
                        goodsEntity.setUnShelveTime(Calendar.getInstance().getTime());
                        goodsEntity.setShelveType(3);
                    }
                    goodsMapper.update(goodsEntity);

                    skuEntity.setSales(skuEntity.getSales() + quantity);
                    skuEntity.setStock(skuEntity.getStock() - quantity);
                    goodsSkuMapper.update(skuEntity);
                    if (goodsEntity.getStock() <= 0) {
                        SerializeObject<List<DataDictionaryBean>> beans = dataDictionaryService.findListByClassification(CommonConstants.MsgType.PRODUCT_DOWN_SHELF.getName(), 1);
                        if (beans != null && beans.getData() != null) {
                            List<DataDictionaryBean> data = beans.getData();
                            if (data != null && data.size() > 0) {
                                for (DataDictionaryBean bean : data) {
                                    Sms sms = new Sms();
                                    sms.setPhone(bean.getItemValue());
                                    sms.setType(SmsType.GOODS_AOTU_UNDER);
                                    Map<String, String> paramMap = new HashMap<>(2);
                                    paramMap.put("goodName", goodsEntity.getName());
                                    sms.setParamMap(paramMap);
                                    amqpTemplate.convertAndSend(QUEUE_MSG_SMS_SEND, sms);
                                }
                            }
                        }
                    }
                }
                return new SerializeObject<>(ResultType.NORMAL, "00000001");
            }

        }
        return new SerializeObject<>(ResultType.ERROR, "00000005");
    }

    @Override
    public boolean succeedOrder(String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            OrderEntity order = orderMapper.selectByOrderNO(orderNO);
            if (order == null) {
                return false;
            }
            int successNum = orderMapper.countSuccessfulNum(order.getUserId());
            if (orderMapper.succeedOrder(orderNO) > 0) {
                if (successNum == 0) {
                    SerializeObject rateBean  = rateSettingsService.findByKeyName(RateKeyEnum.GOLD_BEAN_PROVIDE.getKey(), "");
                    if (rateBean != null && rateBean.getData() != null) {
                        GoldBeanProvide goldBeanProvide = JSON.parseObject(JSONObject.toJSONString(rateBean.getData()), GoldBeanProvide.class);
                        if (goldBeanProvide != null && goldBeanProvide.getFirstBuyGoldOrnament() != null && goldBeanProvide.getFirstBuyGoldOrnament() > 0) {
                            int beans = goldBeanProvide.getFirstBuyGoldOrnament();
                            String memberId = order.getUserId();
                            String remark = GoldBeanRemarkEnum.PAY_ORNAMENT_REWARDS.getRemark();
                            int type = 1;
                            String sign = DigestUtils.md5Hex(beans+memberId+remark+type+NATIVE_PRI_KEY);
                            SerializeObject serializeObject = payGoldBeanRecordService.presentBeans(memberId, beans, type, remark, sign);
                            if (serializeObject != null) {
                                getLog().info("首次金饰购买成功赠送金豆结果：" + serializeObject.getMsg());
                            }
                        }
                    }
                }
                if (order != null && order.getId() > 0) {
                    if (order.getCouponId() > 0) {
                        couponRepertoryService.consumeCoupon(String.valueOf(order.getCouponId()), new BigDecimal(order.getCouponAmount()), order.getSerial());
                    }
                    List<OrderItemEntity> items = orderItemMapper.findListByOrderId(order.getId());
                    if (items != null && items.size() > 0) {
                        Map<Long, Integer> goodsIds = new HashMap<Long, Integer>();
                        for (OrderItemEntity item : items) {
                            GoodsSkuEntity skuEntity = goodsSkuMapper.findById(item.getSkuId());
                            if (skuEntity != null && skuEntity.getId() > 0) {
                                int num = item.getNum();
                                for (Map.Entry<Long, Integer> entry : goodsIds.entrySet()) {
                                    if (entry.getKey() != null && StringUtils.equals(String.valueOf(entry.getKey()), String.valueOf(item.getGoodsId()))) {
                                        int value = entry.getValue() == null ? 0 : entry.getValue();
                                        num += value;
                                    }
                                }
                                goodsIds.put(item.getGoodsId(), num);
                                skuEntity.setSales(skuEntity.getSales() + item.getNum());
                                skuEntity.setStock(skuEntity.getStock() - item.getNum());
                                goodsSkuMapper.update(skuEntity);
                            }
                        }
                        for (Map.Entry<Long, Integer> entry : goodsIds.entrySet()) {
                            GoodsEntity goodsEntity = goodsMapper.findById(entry.getKey());
                            if (goodsEntity != null && goodsEntity.getId() > 0) {
                                goodsEntity.setSales(goodsEntity.getSales() + entry.getValue());
                                goodsEntity.setStock(goodsEntity.getStock() - entry.getValue());
                                if (goodsEntity.getStock() <= 0) {
                                    goodsEntity.setUnShelveTime(Calendar.getInstance().getTime());
                                    goodsEntity.setShelveType(3);
                                }
                                goodsMapper.update(goodsEntity);

                                if (goodsEntity.getStock() <= 0) {
                                    SerializeObject<List<DataDictionaryBean>> beans = dataDictionaryService.findListByClassification(CommonConstants.MsgType.PRODUCT_DOWN_SHELF.getName(), 1);
                                    if (beans != null && beans.getData() != null) {
                                        List<DataDictionaryBean> data = beans.getData();
                                        if (data != null && data.size() > 0) {
                                            for (DataDictionaryBean bean : data) {
                                                Sms sms = new Sms();
                                                sms.setPhone(bean.getItemValue());
                                                sms.setType(SmsType.GOODS_AOTU_UNDER);
                                                Map<String, String> paramMap = new HashMap<>(2);
                                                paramMap.put("goodName", goodsEntity.getName());
                                                sms.setParamMap(paramMap);
                                                amqpTemplate.convertAndSend(QUEUE_MSG_SMS_SEND, sms);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean changeAddress(String orderNO, long addressId) {
        OrderEntity orderEntity = orderMapper.selectByOrderNO(orderNO);
        if (orderEntity == null) {
            return false;
        }
        SerializeObject<MemberLogisticsBean> addressBean = memberAddressService.getLogisticsAddress(addressId);
        if (addressBean != null && addressBean.getData() != null) {
            orderEntity.setAddressId(addressId);
            boolean result = orderMapper.update(orderEntity) > 0 ? true : false;
            if (result) {
                NewLogisticsEntity newLogisticsEntity = newLogisticsMapper.findById(orderEntity.getLogisticsId());
                if (newLogisticsEntity == null) {
                    return false;
                }
                newLogisticsEntity.setAddress(addressBean.getData().getAddress());
                return newLogisticsMapper.update(newLogisticsEntity) > 0 ? true : false;
            }
        }
        return false;
    }

    @Override
    public SerializeObject pay(JSONArray infos, long addressId, int source, String memberId, String cellphone, int couponId) {
        List<OrderItemEntity> items = new ArrayList<OrderItemEntity>();
        OrderEntity order = new OrderEntity();
        order.setStatus(1);
        order.setSource(source);
        order.setOrderType(1);
        order.setUserId(memberId);
        order.setUserName(cellphone);
        order.setAddressId(addressId);
        String orderId = OrderNOPrefixEnum.PG.name() + SerialNumberWorker.getInstance().nextId();
        order.setSerial(orderId);
        GoodsEntity goods = null;
        ProcessTemplateEntity processTemplateEntity = null;
        RateSettingEntity rate = rateSettingsMapper.findByKeyName(RateKeyEnum.FREIGHT.getKey());
        double freight = 0;
        if (rate != null && StringUtils.isNotBlank(rate.getKeyValue())) {
            JSONObject rateJson = JSONObject.parseObject(rate.getKeyValue());
            freight = rateJson.getDouble("fee");
        }
        double processCost = 0;
        order.setExpressFee(new BigDecimal(freight));
        BigDecimal totalGram = BigDecimal.ZERO;
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (int i = 0; i < infos.size(); i++) {
            JSONObject info = infos.getJSONObject(i);
            try {
                int skuId = info.getIntValue("skuId");
                int quantity = info.getIntValue("quantity");
                if (quantity <= 0 || skuId <= 0) {
                    return new SerializeObjectError("00000002");
                }
                GoodsSkuEntity skuEntity = goodsSkuMapper.findById(skuId);
                if (skuEntity == null && skuEntity.getId() <= 0) {
                    return new SerializeObjectError("00000002");
                }
                goods = goodsMapper.findById(skuEntity.getGoodsId());
                if (goods == null) {
                    return new SerializeObjectError("00000002");
                }
                if (goods.getShelveType() != 2) {
                    return new SerializeObjectError("20300215");
                }
                processTemplateEntity = processTemplateMapper.findById(goods.getProcessId());
                if (processTemplateEntity == null) {
                    return new SerializeObjectError("00000002");
                }
                OrderItemEntity itemEntity = new OrderItemEntity();
                itemEntity.setGoodsCode(goods.getGoodsCode());
                itemEntity.setNum(quantity);
                itemEntity.setPrice(skuEntity.getPrice().multiply(new BigDecimal(quantity)));
                itemEntity.setGoodsId(goods.getId());
                itemEntity.setSkuId(skuEntity.getId());
                itemEntity.setWeight(skuEntity.getGram().multiply(new BigDecimal(quantity)));
                processCost += new BigDecimal(Math.ceil(itemEntity.getWeight().doubleValue())).multiply(new BigDecimal(processTemplateEntity.getProcessCost().doubleValue() * processTemplateEntity.getDisCount() / 100)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                totalGram = totalGram.add(itemEntity.getWeight());
                totalAmount = totalAmount.add(itemEntity.getPrice());
                items.add(itemEntity);
            } catch (Exception e) {
                return new SerializeObjectError("00000002");
            }
        }

        Set<Long> goodsIds = new HashSet<Long>();
        for (OrderItemEntity item : items) {
            GoodsSkuEntity skuEntity = goodsSkuMapper.findById(item.getSkuId());
            if (skuEntity == null || item.getNum() > skuEntity.getStock()) {
               if (items.size() > 1) {
                    int stock = skuEntity == null ? 0 : skuEntity.getStock();
                    return new SerializeObject<>(ResultType.STOCK_LACKING, "20300208", item.getSkuId()+":"+stock);
                } else {
                    int stock = skuEntity == null ? 0 : skuEntity.getStock();
                    return new SerializeObject<>(ResultType.STOCK_LACKING, "20300214", item.getSkuId()+":"+stock);
                }
            }
            goodsIds.add(item.getGoodsId());
        }
        List<GoodsPayBean> payBeans = new ArrayList<GoodsPayBean>();
        for (long goodsId : goodsIds) {
            GoodsPayBean bean = new GoodsPayBean();
            bean.setGoodsId(goodsId);
            bean.setTotalGram(BigDecimal.ZERO);
            bean.setTotalNum(0);
            payBeans.add(bean);
        }
        for (OrderItemEntity item : items) {
            for (GoodsPayBean bean : payBeans) {
                if (StringUtils.equals(String.valueOf(item.getGoodsId()), String.valueOf(bean.getGoodsId()))) {
                    bean.setTotalNum(bean.getTotalNum() + item.getNum());
                    bean.setTotalGram(bean.getTotalGram().add(item.getWeight()));
                    break;
                }
            }
        }
        for (GoodsPayBean bean : payBeans) {
            GoodsEntity goodsEntity = goodsMapper.findById(bean.getGoodsId());
            if (goodsEntity == null) {
                return new SerializeObjectError("20300200");
            }
            Calendar calendar = Calendar.getInstance();
            if (goodsEntity.getIsPrompt() == 1 && goodsEntity.getStartPrompt() != null && calendar.getTime().getTime() < goodsEntity.getStartPrompt().getTime()) {
                return new SerializeObjectError("20300202");
            }
            if (goodsEntity.getIsPrompt() == 1 && goodsEntity.getEndPrompt() != null && calendar.getTime().getTime() > goodsEntity.getEndPrompt().getTime()) {
                return new SerializeObjectError("20300202");
            }
            if (goodsEntity.getIsQuota() == 1 && goodsEntity.getQuotaNum() > 0) {
                int num = orderItemMapper.selectNumByMemberId(goodsEntity.getId(), order.getUserId());
                if ((num + bean.getTotalNum()) > goodsEntity.getQuotaNum()) {
                    return new SerializeObjectError("20300203");
                }
            }
            if (goodsEntity.getIsQuota() == 2 && goodsEntity.getQuotaWeight() != null && goodsEntity.getQuotaWeight().doubleValue() > 0) {
                double weight = orderMapper.selectTotalGramByMemberId(goodsEntity.getId(), order.getUserId());
                if ((weight + bean.getTotalGram().doubleValue()) > goodsEntity.getQuotaWeight().doubleValue()) {
                    return new SerializeObjectError("20300207");
                }
            }
        }
        order.setProcessCost(new BigDecimal(processCost));
        order.setAmount(totalAmount);
        order.setTotalGram(totalGram);
        if (couponId > 0) {
            SerializeObject<CouponMemberBean> couponBean = couponRepertoryService.getMemberCoupon(String.valueOf(couponId));
            if (couponBean == null || couponBean.getData() == null || couponBean.getData().getStatus() != 1 || couponBean.getData().getTransactionAmount() > totalAmount.doubleValue()) {
                Ensure.that(true).isTrue("00000005");
            }
            order.setCouponId(couponId);
            order.setCouponAmount(couponBean.getData().getDiscountAmount());
        } else {
            order.setCouponAmount(0);
        }
        SerializeObject<MemberLogisticsBean> addressBean = memberAddressService.getLogisticsAddress(addressId);
        if (addressBean != null && addressBean.getData() != null) {
            NewLogisticsEntity logistics = new NewLogisticsEntity();
            logistics.setAddress(addressBean.getData().getAddress());
            logistics.setFullName(addressBean.getData().getFullName());
            logistics.setTelephone(addressBean.getData().getTelephone());
            newLogisticsMapper.insert(logistics);
            order.setLogisticsId(logistics.getId());
            order.setMoney(order.getAmount().add(order.getExpressFee()).add(order.getProcessCost()).subtract(new BigDecimal(order.getCouponAmount())));
            if (orderMapper.insert(order) > 0) {
                for (OrderItemEntity item : items) {
                    item.setOrderId(order.getId());
                    int raws = orderItemMapper.insert(item);
                    Ensure.that(raws < 1).isTrue("00000005");
                    shoppingTrolleyMapper.deleteBySkuId(memberId, item.getSkuId());
                }
                if (couponId > 0) {
                    couponRepertoryService.lock(String.valueOf(couponId));
                }
                return new SerializeObject<>(ResultType.NORMAL, "00000001", orderId);
            }

        }
        return new SerializeObjectError("00000005");
    }

    @Override
    public SerializeObject findById(Long id) {
        OrderEntity entity = orderMapper.findById(id);
        if (entity != null) {
            OrderDetailBean detail = dozerBeanMapper.map(entity, OrderDetailBean.class);

            if (entity.getOrderType() > 1) {//提金 换金
                detail.setAmount(detail.getProcessCost().add(detail.getExpressFee()));
            }

            List<OrderItemGoodsBean> items = orderItemMapper.getOrderItemGoodsBeanByOrderId(id);
            List<OrderItemGoodsBean> itemList = new ArrayList<>();
            if (items != null) {
                for (OrderItemGoodsBean bean : items) {
                    if(entity.getOrderType() == 1) {
                        BigDecimal cost = bean.getGram().setScale(0,BigDecimal.ROUND_UP).multiply(bean.getProcessCost());
                        bean.setProcessCost(cost.multiply(BigDecimal.valueOf(bean.getNum())));
                    }
                    if (entity.getOrderType() == 2) {//提金
                        bean.setProcessCost(entity.getProcessCost());
                    }

                    if (entity.getOrderType() == 3) {//换金
                        bean.setProcessCost(entity.getProcessCost());
                    }
                    itemList.add(bean);
                }
            }

            detail.setItemList(itemList);

            // 订单物流 收货地址
            NewLogisticsEntity logistics = newLogisticsMapper.findById(entity.getLogisticsId());
            if (logistics != null) {
                detail.setFullName(logistics.getFullName());
                detail.setTelephone(logistics.getTelephone());
                detail.setAddress(logistics.getAddress());
                detail.setLogisticsNo(logistics.getLogisticsNo());
                detail.setLogisticsName(logistics.getLogisticsName());
                detail.setZipCode(logistics.getZipCode());
            }

            if (OrderStatusEnum.WAIT_PAY.getCode() == entity.getStatus()) {
                LocalDateTime time = UF.date2LocalDateTime(entity.getAddTime());
                LocalDateTime endTime = time.plus(1, ChronoUnit.DAYS);
                Duration duration = Duration.between(time, endTime);
                long minutes = duration.toMinutes();
                minutes = minutes < 0 ? 0 : minutes;
                long hours = minutes / 60;
                minutes = minutes % 60;
                detail.setHint(String.format("剩余支付时间：%s小时%s分", hours, minutes));
            }

            return new SerializeObject<>(ResultType.NORMAL, "00000001", detail);
        }
        return new SerializeObjectError<>("00000005");
    }

    @Override
    public SerializeObject findBySerial(String serial) {
        OrderEntity entity = orderMapper.findBySerial(serial);
        if (entity != null) {
            OrderDetailBean detail = dozerBeanMapper.map(entity, OrderDetailBean.class);

            if (entity.getOrderType() > 1) {//提金 换金
                detail.setAmount(detail.getProcessCost().add(detail.getExpressFee()));
            }

            List<OrderItemGoodsBean> items = orderItemMapper.getOrderItemGoodsBeanByOrderId(entity.getId());
            List<OrderItemGoodsBean> itemList = new ArrayList<>();
            if (items != null) {
                for (OrderItemGoodsBean bean : items) {
                    if(entity.getOrderType() == 1) {
                        ProcessTemplateEntity process = processTemplateMapper.findById(bean.getProcessId());
                        double cost = new BigDecimal(Math.ceil(bean.getGram().doubleValue())).multiply(
                                new BigDecimal(process.getProcessCost().doubleValue() * process.getDisCount() / 100))
                                .setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

                        bean.setProcessCost(BigDecimal.valueOf(cost));
                    }
                    if (entity.getOrderType() == 2) {//提金
                        bean.setProcessCost(entity.getProcessCost());
                    }

                    if (entity.getOrderType() == 3) {//换金
                        bean.setProcessCost(entity.getProcessCost());
                    }
                    itemList.add(bean);
                }
            }

            detail.setItemList(itemList);

            // 订单物流 收货地址
            NewLogisticsEntity logistics = newLogisticsMapper.findById(entity.getLogisticsId());
            if (logistics != null) {
                detail.setFullName(logistics.getFullName());
                detail.setTelephone(logistics.getTelephone());
                detail.setAddress(logistics.getAddress());
                detail.setLogisticsNo(logistics.getLogisticsNo());
                detail.setLogisticsName(logistics.getLogisticsName());
                detail.setZipCode(logistics.getZipCode());
            }

            if (OrderStatusEnum.WAIT_PAY.getCode() == entity.getStatus()) {
                LocalDateTime time = UF.date2LocalDateTime(entity.getAddTime());
                LocalDateTime endTime = time.plus(1, ChronoUnit.DAYS);
                Duration duration = Duration.between(time, endTime);
                long minutes = duration.toMinutes();
                minutes = minutes < 0 ? 0 : minutes;
                long hours = minutes / 60;
                minutes = minutes % 60;
                detail.setHint(String.format("剩余支付时间：%s小时%s分", hours, minutes));
            }

            return new SerializeObject<>(ResultType.NORMAL, "00000001", detail);
        }
        return new SerializeObjectError<>("00000005");
    }

    /**
     * 后台订单列表
     *
     * @param submit
     * @return
     */
    @Override
    public SerializeObject findList(OrderSearchSubmit submit) {
        submit.setPlatform(1);
        QuerySubmit querySubmit = new QuerySubmit();
        submit.setParams(querySubmit);
        querySubmit.put("platform",1);
        int count = orderMapper.count(querySubmit);
        Page page = new Page(submit.getPageNum(), submit.getPageSize(), count);
        List<OrderBean> list = new ArrayList<>(count);
        if (count > 0) {
            List<OrderEntity> orderList = orderMapper.findList(querySubmit);
            Iterator<OrderEntity> iterator = orderList.iterator();
            while (iterator.hasNext()) {
                OrderEntity entity = iterator.next();
                OrderBean bean = dozerBeanMapper.map(entity, OrderBean.class);
                list.add(bean);
            }
        }
        return new SerializeObject<>(ResultType.NORMAL, "00000001", new DataTable<>(page, list));
    }

    @Override
    @Transactional
    public SerializeObject closeOrder(OtherSubmit submit) {

        OrderEntity entity = orderMapper.findById(submit.getId());
        if (entity != null) {
            entity.setCloseRemark(submit.getCloseRemark());
            int success = orderMapper.closeOrder(entity);
            if (success > 0) {
//                List<OrderItemEntity> itemList = orderItemMapper.findListByOrderId(entity.getId());
//                //加库存 减销量
//                for (OrderItemEntity item : itemList) {
//                    this.updateGoodsStockSales(item);
//                }
                return new SerializeObject<>(ResultType.NORMAL, "00000001");
            }
        }

        return new SerializeObjectError("00000005");
    }

//    public void updateGoodsStockSales(OrderItemEntity item) {
//        String key = "updateGoodsStock:" + item.getGoodsId() + ":" + item.getSkuId();
//        if (redisGlobalLock.lock(key)) {
//            try {
//                goodsMapper.updateGoodsStockSales(item.getGoodsId(), item.getNum());
//                goodsSkuMapper.updateGoodsStockSales(item.getSkuId(), item.getNum());
//            } catch (Exception e) {
//                throw e;
//            } finally {
//                redisGlobalLock.unlock(key);
//            }
//        }
//    }

    /**
     * 查询后台订单备注
     *
     * @param orderId
     * @return
     */
    @Override
    public SerializeObject findRemark(long orderId) {
        OrderEntity entity = orderMapper.findById(orderId);
        if (entity != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("id", entity.getId());
            map.put("serverRemark", entity.getServerRemark());
            map.put("closeRemark", entity.getCloseRemark());
            return new SerializeObject<>(ResultType.NORMAL, "00000001", map);
        }
        return new SerializeObjectError("00000005");
    }

    /**
     * 更新订单备注信息
     *
     * @param submit
     * @return
     */
    @Override
    public SerializeObject remarkOrder(OtherSubmit submit) {
        if (StringUtils.isEmpty(submit.getServerRemark())) {
            return new SerializeObject<>(ResultType.NORMAL, "00000001");
        }
        OrderEntity order = orderMapper.findById(submit.getId());
        if (order != null) {
            OrderEntity entity = dozerBeanMapper.map(submit, OrderEntity.class);
            entity.setServerRemark(submit.getServerRemark());
            int success = orderMapper.updateServerRemark(entity);
            if (success > 0) {
                return new SerializeObject<>(ResultType.NORMAL, "00000001");
            }
        }
        return new SerializeObjectError("00000005");
    }

    /**
     * 移动端订单列表
     *
     * @param searchSubmit
     * @return
     */
    @Override
    public SerializeObject getOrderList(OrderSearchSubmit searchSubmit) {
        searchSubmit.setPlatform(2);
        LoginBean loginBean = LoginHelper.getLoginBean();
        if (loginBean == null || StringUtils.isEmpty(loginBean.getId())) {
            return new SerializeObjectError<>("00000102");
        }
        if (searchSubmit.getStatus() == null) {
            searchSubmit.setStatus(0);
        }
        QuerySubmit querySubmit = new QuerySubmit();
        searchSubmit.setParams(querySubmit);
        querySubmit.put("userId", loginBean.getId());
        querySubmit.put("platform", 2);
        querySubmit.put("status", searchSubmit.getStatus());

        int count = orderMapper.count(querySubmit);
        Page page = new Page(searchSubmit.getPageNum(), searchSubmit.getPageSize(), count);
        List<OrderDetailBean> list = new ArrayList<>(count);

        if (count > 0) {
            List<OrderEntity> orderList = orderMapper.findList(querySubmit);
            List<Long> ids = orderList.stream().map(OrderEntity::getId).collect(Collectors.toList());
            List<OrderItemGoodsBean> itemBeanList = orderItemMapper.getOrderItemGoodsBeanByOrderIds(ids);
            for (OrderEntity entity : orderList) {
                OrderDetailBean detail = dozerBeanMapper.map(entity, OrderDetailBean.class);
                List<OrderItemGoodsBean> itemList = itemBeanList.stream().filter(a -> a.getOrderId().equals(entity.getId())).collect(Collectors.toList());
                detail.setItemList(itemList);
                list.add(detail);
            }
        }

        return new SerializeObject<>(ResultType.NORMAL, "00000001", new DataTable<>(page, list));
    }

    /**
     * 订单发货
     *
     * @param submit
     * @return
     */
    @Override
    @Transactional
    public SerializeObject orderDelivery(OtherSubmit submit) {

        OrderEntity entity = orderMapper.findById(submit.getId());
        if (entity != null && entity.getStatus() == OrderStatusEnum.WAIT_SEND.getCode()) {
            NewLogisticsEntity logistics = newLogisticsMapper.findById(entity.getLogisticsId());
            if (logistics != null) {
                NewLogisticsEntity logisticsEntity = new NewLogisticsEntity();
                logisticsEntity.setId(entity.getLogisticsId());
                logisticsEntity.setLogisticsName("顺丰快递");
                logisticsEntity.setLogisticsNo(submit.getLogisticsNo());
                newLogisticsMapper.update(logisticsEntity);
            }
            entity.setStatus(OrderStatusEnum.DELIVERED.getCode());
            orderMapper.orderDelivery(entity);

            return new SerializeObject<>(ResultType.NORMAL, "00000001");
        }

        return new SerializeObjectError("00000005");
    }

    @Override
    public SerializeObject orderTrack(long id) {
        OrderEntity entity = orderMapper.findById(id);
        if (entity != null && entity.getLogisticsId() > 0) {

            NewLogisticsEntity logistics = newLogisticsMapper.findById(entity.getLogisticsId());
            if (logistics == null || StringUtils.isEmpty(logistics.getLogisticsNo())) {
                return new SerializeObjectError("20300212");
            }

            List<OrderLogisticsBean> list = new ArrayList<>();
            if (logistics.getState() != LogisticsStatusEnum.SIGN.state()) {
                Result result = kd100Service.queryOrderTrace(KD100LogisticsEnum.SHUN_FENG.number(), logistics.getLogisticsNo());

                if (result != null && "200".equals(result.getStatus())) {
                    int state = Integer.parseInt(result.getState());
                    String desc = LogisticsStatusEnum.get(state).desc();
                    ArrayList<ResultItem> data = result.getData();
                    if (CollectionUtils.isNotEmpty(data)) {
                        ResultItem resultItem = data.get(0);
                        resultItem.setContext(desc + "，" + resultItem.getContext());
                        for (ResultItem item : data) {
                            OrderLogisticsBean bean = new OrderLogisticsBean();
                            bean.setContext(item.getContext());
                            bean.setTime(UF.strToDate(item.getFtime(), "yyyy-MM-dd HH:mm:ss"));
                            list.add(bean);
                        }
                    }
                    logistics.setState(state);
                }
                String data = JSON.toJSONString(list);

                list.add(new OrderLogisticsBean("订单付款成功", entity.getPayTime()));
                list.add(new OrderLogisticsBean("订单已提交等待支付", entity.getAddTime()));

                logistics.setData(data);

                newLogisticsMapper.update(logistics);
                if (logistics.getState() == 3) {
                    orderMapper.receiveOrder(id);
                }
                return new SerializeObject<>(ResultType.NORMAL, "00000001", list);
            }

            if (logistics.getState() == LogisticsStatusEnum.SIGN.state()) {
                String data = logistics.getData();
                if (data != null) {
                    List<OrderLogisticsBean> logisticsBeans = JSONObject.parseArray(data, OrderLogisticsBean.class);
                    int index = logisticsBeans == null ? 0 : logisticsBeans.size();
                    logisticsBeans.add(index, new OrderLogisticsBean("订单付款成功", entity.getPayTime()));
                    logisticsBeans.add(index + 1, new OrderLogisticsBean("订单已提交等待支付", entity.getAddTime()));
                    return new SerializeObject<>(ResultType.NORMAL, "00000001", logisticsBeans);
                }
            }
        }
        return new SerializeObjectError("00000005");
    }

    @Override
    public boolean failOrder(String orderNO, String closeRemark) {
        if (StringUtils.isNotBlank(orderNO)) {
            return orderMapper.failOrder(orderNO, closeRemark) > 0;
        }
        return false;
    }

    @Override
    public boolean handlingOrder(String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            return orderMapper.handlingOrder(orderNO) > 0;
        }
        return false;
    }

    @Override
    public OrderBean getOrder(String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            OrderEntity entity = orderMapper.selectByOrderNO(orderNO);
            if (entity != null) {
                return dozerBeanMapper.map(entity, OrderBean.class);
            }
        }
        return null;
    }


    @Override
    public boolean updateNeedCloseOrder() {
        List<OrderEntity> items = orderMapper.getNeedCloseOrderList();
        if (items != null && items.size() > 0) {
            List<Long> ids = new ArrayList<Long>();
            for (OrderEntity entity : items) {
                ids.add(entity.getId());
                if (entity.getCouponId() > 0) {
                    couponRepertoryService.unlock(String.valueOf(entity.getCouponId()));
                }
            }
            int success = orderMapper.updateNeedCloseOrder(ids, "订单超时，系统自动关闭");
            return success > 0;
        }
        return false;
    }

    @Override
    public boolean read(String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            return orderMapper.read(orderNO) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public int countUnreadNum(String memberId, int status) {
        if (StringUtils.isNotBlank(memberId)) {
            return orderMapper.countUnreadNum(memberId, status);
        }
        return 0;
    }

    @Override
    public int countSuccessfulNum(String memberId) {
        if (StringUtils.isNotBlank(memberId)) {
            return orderMapper.countSuccessfulNum(memberId);
        }
        return 0;
    }
}

